﻿#include "QCefClient.h"
#include "QCefDownFavicon.h"
#include "QCefDelegate.h"

//////////////////////////////////////////////////////////////////////////
//QCefBrowserClient
QCefClient::QCefClient(QCefApp * app, CefRefPtr<QCefDelegate> gate)
    : m_app(app)
{
    QCEF_DEBUG();

    if (m_app != nullptr)
    {
        m_app->checkInClient(this);
    }

    this->setDelegate(gate);
}

QCefClient::~QCefClient()
{
    QCEF_DEBUG();

    //
    m_delegate.storeRelease(nullptr);
    m_gate = nullptr;

    //
    if (m_app != nullptr)
    {
        m_app->checkOutClient(this);
    }
    m_app = nullptr;
}

int QCefClient::finiClient()
{
    QCEF_DEBUG();

    //
    m_delegate.storeRelease(nullptr);
    m_gate = nullptr;

    //
    //m_browser = nullptr;

    // Remove from the list of existing browsers.
    BrowserList temp(m_browserList);
    for (BrowserList::iterator it = temp.begin(); it != temp.end(); ++it)
    {
        (*it)->StopLoad();
        (*it)->GetHost()->CloseBrowser(true);
    }
    //closeAllBrowsers();

    return 0;
}

void QCefClient::closeAllBrowsers()
{
    QCEF_DEBUG();

    if (!CefCurrentlyOn(TID_UI))
    {
        // Execute on the UI thread.
        CefPostTask(TID_UI, base::BindOnce(&QCefClient::closeAllBrowsers, this));
        return;
    }

    //
    BrowserList temp(m_browserList);
    for (BrowserList::iterator it = temp.begin(); it != temp.end(); ++it)
    {
        (*it)->StopLoad();
        (*it)->GetHost()->CloseBrowser(true);
    }
}

//////////////////////////////////////////////////////////////////////////
//CefClient
CefRefPtr<CefAudioHandler> QCefClient::GetAudioHandler()
{
    QCEF_DEBUG();

    return nullptr;
}


//CefRefPtr<CefCommandHandler> QCefBrowserClient::GetCommandHandler()
//{
//    QCEF_DEBUG();

//    return nullptr;
//}


CefRefPtr<CefContextMenuHandler> QCefClient::GetContextMenuHandler()
{
    QCEF_DEBUG();

    return nullptr;
}

CefRefPtr<CefDialogHandler> QCefClient::GetDialogHandler()
{
    QCEF_DEBUG();

    return nullptr;
}

CefRefPtr<CefDisplayHandler> QCefClient::GetDisplayHandler()
{
    QCEF_DEBUG();

    return this;
}

CefRefPtr<CefDownloadHandler> QCefClient::GetDownloadHandler()
{
    QCEF_DEBUG();

    return this;
}

CefRefPtr<CefDragHandler> QCefClient::GetDragHandler()
{
    QCEF_DEBUG();

    return nullptr;
}

CefRefPtr<CefFindHandler> QCefClient::GetFindHandler()
{
    QCEF_DEBUG();

    return nullptr;
}

CefRefPtr<CefFocusHandler> QCefClient::GetFocusHandler()
{
    QCEF_DEBUG();

    return nullptr;
}


CefRefPtr<CefFrameHandler> QCefClient::GetFrameHandler()
{
    QCEF_DEBUG();

    return nullptr;
}


CefRefPtr<CefJSDialogHandler> QCefClient::GetJSDialogHandler()
{
    QCEF_DEBUG();

    return nullptr;
}

CefRefPtr<CefKeyboardHandler> QCefClient::GetKeyboardHandler()
{
    QCEF_DEBUG();

    return nullptr;
}

CefRefPtr<CefLifeSpanHandler> QCefClient::GetLifeSpanHandler()
{
    QCEF_DEBUG();

    return this;
}

CefRefPtr<CefLoadHandler> QCefClient::GetLoadHandler()
{
    QCEF_DEBUG();

    return this;
}


CefRefPtr<CefPrintHandler> QCefClient::GetPrintHandler()
{
    QCEF_DEBUG();

    return nullptr;
}


CefRefPtr<CefRenderHandler> QCefClient::GetRenderHandler()
{
    QCEF_DEBUG();

    return nullptr;
}

CefRefPtr<CefRequestHandler> QCefClient::GetRequestHandler()
{
    QCEF_DEBUG();

    return this;
}

bool QCefClient::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                                          CefRefPtr<CefFrame> frame,
                                          CefProcessId source_process,
                                          CefRefPtr<CefProcessMessage> message)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnProcessMessageReceived(browser, frame, source_process, message);
    }

    return ret;
}



//////////////////////////////////////////////////////////////////////////
//CefLifeSpanHandler
bool QCefClient::OnBeforePopup(CefRefPtr<CefBrowser> browser,
                               CefRefPtr<CefFrame> frame,
                               const CefString& target_url,
                               const CefString& target_frame_name,
                               CefLifeSpanHandler::WindowOpenDisposition target_disposition,
                               bool user_gesture,
                               const CefPopupFeatures& popupFeatures,
                               CefWindowInfo& windowInfo,
                               CefRefPtr<CefClient>& client,
                               CefBrowserSettings& settings,
                               CefRefPtr<CefDictionaryValue>& extra_info,
                               bool* no_javascript_access)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnBeforePopup(browser,
                                      frame,
                                      target_url,
                                      target_frame_name,
                                      target_disposition,
                                      user_gesture,
                                      popupFeatures,
                                      windowInfo,
                                      client,
                                      settings,
                                      extra_info,
                                      no_javascript_access);
    }

    return ret;
}

void QCefClient::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
    QCEF_DEBUG();

    //保存主浏览器
    //m_browser = browser;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnAfterCreated(browser);
    }

    //
    if (std::find(m_browserList.begin(), m_browserList.end(), browser) == m_browserList.end())
    {
        m_browserList.push_back(browser);
    }
}


bool QCefClient::DoClose(CefRefPtr<CefBrowser> browser)
{
    QCEF_DEBUG();

    //清空主浏览器引用
    //if (m_browser != nullptr && browser != nullptr && browser->IsSame(m_browser))
    //{
    //    m_browser = nullptr;
    //}

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->DoClose(browser);
    }

    return ret;
}

void QCefClient::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
    QCEF_DEBUG();

    //清空主浏览器引用
    //if (m_browser != nullptr && browser != nullptr && browser->IsSame(m_browser))
    //{
    //    m_browser = nullptr;
    //}

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnBeforeClose(browser);
    }

    // Remove from the list of existing browsers.
    for (BrowserList::iterator it = m_browserList.begin(); it != m_browserList.end(); )
    {
        if ((*it)->IsSame(browser))
        {
            it = m_browserList.erase(it);
        }
        else
        {
            ++it;
        }
    }

    browser->GetHost()->CloseBrowser(true);
}


//////////////////////////////////////////////////////////////////////////
//CefLoadHandler
void QCefClient::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
                                      bool isLoading,
                                      bool canGoBack,
                                      bool canGoForward)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnLoadingStateChange(browser, isLoading, canGoBack, canGoForward);
    }
}

void QCefClient::OnLoadStart(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
                             CefLoadHandler::TransitionType transition_type)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnLoadStart(browser, frame, transition_type);
    }
}


void QCefClient::OnLoadEnd(CefRefPtr<CefBrowser> browser,
                           CefRefPtr<CefFrame> frame,
                           int httpStatusCode)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnLoadEnd(browser, frame, httpStatusCode);
    }
}


void QCefClient::OnLoadError(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
                             CefLoadHandler::ErrorCode errorCode,
                             const CefString& errorText,
                             const CefString& failedUrl)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnLoadError(browser, frame, errorCode, errorText, failedUrl);
    }
}



//////////////////////////////////////////////////////////////////////////
//CefDisplayHandler
void QCefClient::OnAddressChange(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 const CefString & url)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnAddressChange(browser, frame, url);
    }
}

void QCefClient::OnTitleChange(CefRefPtr<CefBrowser> browser,
                               const CefString & title)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnTitleChange(browser, title);
    }
}


void QCefClient::OnFaviconURLChange(CefRefPtr<CefBrowser> browser,
                                    const std::vector<CefString>& icon_urls)
{
    QCEF_DEBUG();

    //
    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnFaviconURLChange(browser, icon_urls);
    }

    //下载第一个favicon，下载完成后回调OnFaviconChange函数。
    if (!icon_urls.empty())
    {
        //browser->GetHost()->DownloadImage(icon_urls[0], true, 0, true, new QCefDownFavicon(m_delegate));
        browser->GetHost()->DownloadImage(icon_urls[0], true, 0, true, new QCefDownFavicon(m_gate));
    }
}


void QCefClient::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
                                        bool fullscreen)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnFullscreenModeChange(browser, fullscreen);
    }
}


bool QCefClient::OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnTooltip(browser, text);
    }

    return ret;
}


void QCefClient::OnStatusMessage(CefRefPtr<CefBrowser> browser,
                                 const CefString& value)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnStatusMessage(browser, value);
    }
}


bool QCefClient::OnConsoleMessage(CefRefPtr<CefBrowser> browser,
                                  cef_log_severity_t level,
                                  const CefString& message,
                                  const CefString& source,
                                  int line)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnConsoleMessage(browser, level, message, source, line);
    }

    return ret;
}


bool QCefClient::OnAutoResize(CefRefPtr<CefBrowser> browser,
                              const CefSize & new_size)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnAutoResize(browser, new_size);
    }

    return ret;
}


void QCefClient::OnLoadingProgressChange(CefRefPtr<CefBrowser> browser,
                                         double progress)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnLoadingProgressChange(browser, progress);
    }
}


bool QCefClient::OnCursorChange(CefRefPtr<CefBrowser> browser,
                                CefCursorHandle cursor,
                                cef_cursor_type_t type,
                                const CefCursorInfo& custom_cursor_info)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnCursorChange(browser, cursor, type, custom_cursor_info);
    }

    return ret;
}

//////////////////////////////////////////////////////////////////////////
//CefFocusHandler
void QCefClient::OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnTakeFocus(browser, next);
    }
}

bool QCefClient::OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnSetFocus(browser, source);
    }

    return ret;
}

void QCefClient::OnGotFocus(CefRefPtr<CefBrowser> browser)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnGotFocus(browser);
    }
}


//////////////////////////////////////////////////////////////////////////
//CefRenderHandler
CefRefPtr<CefAccessibilityHandler> QCefClient::GetAccessibilityHandler()
{
    QCEF_DEBUG();

    CefRefPtr<CefAccessibilityHandler> ret;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetAccessibilityHandler();
    }

    return ret;
}

bool QCefClient::GetRootScreenRect(CefRefPtr<CefBrowser> browser, CefRect& rect)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetRootScreenRect(browser, rect);
    }

    return ret;
}

void QCefClient::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->GetViewRect(browser, rect);
    }
}

bool QCefClient::GetScreenPoint(CefRefPtr<CefBrowser> browser,
                                int viewX,
                                int viewY,
                                int& screenX,
                                int& screenY)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetScreenPoint(browser, viewX, viewY, screenX, screenY);
    }

    return ret;
}

bool QCefClient::GetScreenInfo(CefRefPtr<CefBrowser> browser,
                               CefScreenInfo& screen_info)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetScreenInfo(browser, screen_info);
    }

    return ret;
}

void QCefClient::OnPopupShow(CefRefPtr<CefBrowser> browser, bool show)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnPopupShow(browser, show);
    }
}

void QCefClient::OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnPopupSize(browser, rect);
    }
}

void QCefClient::OnPaint(CefRefPtr<CefBrowser> browser,
                         PaintElementType type,
                         const RectList& dirtyRects,
                         const void* buffer,
                         int width,
                         int height)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnPaint(browser, type, dirtyRects, buffer, width, height);
    }
}

void QCefClient::OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
                                    PaintElementType type,
                                    const RectList& dirtyRects,
                                    void* shared_handle)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnAcceleratedPaint(browser, type, dirtyRects, shared_handle);
    }
}

bool QCefClient::StartDragging(CefRefPtr<CefBrowser> browser,
                               CefRefPtr<CefDragData> drag_data,
                               DragOperationsMask allowed_ops,
                               int x,
                               int y)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->StartDragging(browser, drag_data, allowed_ops, x, y);
    }

    return ret;
}

void QCefClient::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
                                  DragOperation operation)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->UpdateDragCursor(browser, operation);
    }
}

void QCefClient::OnScrollOffsetChanged(CefRefPtr<CefBrowser> browser,
                                       double x,
                                       double y)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnScrollOffsetChanged(browser, x, y);
    }
}

void QCefClient::OnImeCompositionRangeChanged(CefRefPtr<CefBrowser> browser,
                                              const CefRange& selected_range,
                                              const RectList& character_bounds)
{
    QCEF_DEBUG();
    //qDebug() << "CefRange, from=" << selected_range.from << ", to=" << selected_range.to;
    //for (auto& rect : character_bounds)
    //{
    //    qDebug() << "RectList, CefRect, x=" << rect.x << ", y=" << rect.y << ", width=" << rect.width << ", height=" << rect.height;
    //}

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnImeCompositionRangeChanged(browser, selected_range, character_bounds);
    }
}

void QCefClient::OnTextSelectionChanged(CefRefPtr<CefBrowser> browser,
                                        const CefString& selected_text,
                                        const CefRange& selected_range)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnTextSelectionChanged(browser, selected_text, selected_range);
    }
}

void QCefClient::OnVirtualKeyboardRequested(CefRefPtr<CefBrowser> browser,
                                            TextInputMode input_mode)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnVirtualKeyboardRequested(browser, input_mode);
    }
}


//////////////////////////////////////////////////////////////////////////
//CefRequestHandler
bool QCefClient::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefFrame> frame,
                                CefRefPtr<CefRequest> request,
                                bool user_gesture,
                                bool is_redirect)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnBeforeBrowse(browser, frame, request, user_gesture, is_redirect);
    }

    return ret;
}

bool QCefClient::OnOpenURLFromTab(CefRefPtr<CefBrowser> browser,
                                  CefRefPtr<CefFrame> frame,
                                  const CefString& target_url,
                                  CefRequestHandler::WindowOpenDisposition target_disposition,
                                  bool user_gesture)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnOpenURLFromTab(browser, frame, target_url, target_disposition, user_gesture);
    }

    return ret;
}

CefRefPtr<CefResourceRequestHandler> QCefClient::GetResourceRequestHandler(CefRefPtr<CefBrowser> browser,
                                                                           CefRefPtr<CefFrame> frame,
                                                                           CefRefPtr<CefRequest> request,
                                                                           bool is_navigation,
                                                                           bool is_download,
                                                                           const CefString& request_initiator,
                                                                           bool& disable_default_handling)
{
    QCEF_DEBUG();

    return this;

    //CefRefPtr<CefResourceRequestHandler> ret;
    //for (DelegateList::iterator it = m_delegateList.begin(); it != m_delegateList.end(); ++it)
    //{
    //    ret = (*it)->GetResourceRequestHandler(browser, frame, request, is_navigation, is_download, request_initiator, disable_default_handling);
    //}
    //return ret;
}


bool QCefClient::GetAuthCredentials(CefRefPtr<CefBrowser> browser,
                                    const CefString& origin_url,
                                    bool isProxy,
                                    const CefString& host,
                                    int port,
                                    const CefString& realm,
                                    const CefString& scheme,
                                    CefRefPtr<CefAuthCallback> callback)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetAuthCredentials(browser, origin_url, isProxy, host, port, realm, scheme, callback);
    }

    return ret;
}


bool QCefClient::OnQuotaRequest(CefRefPtr<CefBrowser> browser,
                                const CefString& origin_url,
                                int64 new_size,
                                CefRefPtr<CefCallback> callback)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnQuotaRequest(browser, origin_url, new_size, callback);
    }

    return ret;
}


bool QCefClient::OnCertificateError(CefRefPtr<CefBrowser> browser,
                                    cef_errorcode_t cert_error,
                                    const CefString& request_url,
                                    CefRefPtr<CefSSLInfo> ssl_info,
                                    CefRefPtr<CefCallback> callback)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnCertificateError(browser, cert_error, request_url, ssl_info, callback);
    }

    return ret;
}


bool QCefClient::OnSelectClientCertificate(CefRefPtr<CefBrowser> browser,
                                           bool isProxy,
                                           const CefString& host,
                                           int port,
                                           const X509CertificateList& certificates,
                                           CefRefPtr<CefSelectClientCertificateCallback> callback)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnSelectClientCertificate(browser, isProxy, host, port, certificates, callback);
    }

    return ret;
}


void QCefClient::OnRenderViewReady(CefRefPtr<CefBrowser> browser)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnRenderViewReady(browser);
    }
}


void QCefClient::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
                                           TerminationStatus status)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnRenderProcessTerminated(browser, status);
    }
}


void QCefClient::OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnDocumentAvailableInMainFrame(browser);
    }
}


//////////////////////////////////////////////////////////////////////////
//CefResourceRequestHandler
CefRefPtr<CefCookieAccessFilter> QCefClient::GetCookieAccessFilter(CefRefPtr<CefBrowser> browser,
                                                                   CefRefPtr<CefFrame> frame,
                                                                   CefRefPtr<CefRequest> request)
{
    QCEF_DEBUG();

    CefRefPtr<CefCookieAccessFilter> ret;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetCookieAccessFilter(browser, frame, request);
    }

    return ret;
}

CefResourceRequestHandler::ReturnValue QCefClient::OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
                                                                        CefRefPtr<CefFrame> frame,
                                                                        CefRefPtr<CefRequest> request,
                                                                        CefRefPtr<CefCallback> callback)
{
    QCEF_DEBUG();

    CefResourceRequestHandler::ReturnValue ret = RV_CONTINUE;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnBeforeResourceLoad(browser, frame, request, callback);
    }

    return ret;
}

CefRefPtr<CefResourceHandler> QCefClient::GetResourceHandler(CefRefPtr<CefBrowser> browser,
                                                             CefRefPtr<CefFrame> frame,
                                                             CefRefPtr<CefRequest> request)
{
    QCEF_DEBUG();

    CefRefPtr<CefResourceHandler> ret;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetResourceHandler(browser, frame, request);
    }

    return ret;
}

void QCefClient::OnResourceRedirect(CefRefPtr<CefBrowser> browser,
                                    CefRefPtr<CefFrame> frame,
                                    CefRefPtr<CefRequest> request,
                                    CefRefPtr<CefResponse> response,
                                    CefString& new_url)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnResourceRedirect(browser, frame, request, response, new_url);
    }
}

bool QCefClient::OnResourceResponse(CefRefPtr<CefBrowser> browser,
                                    CefRefPtr<CefFrame> frame,
                                    CefRefPtr<CefRequest> request,
                                    CefRefPtr<CefResponse> response)
{
    QCEF_DEBUG();

    bool ret = false;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->OnResourceResponse(browser, frame, request, response);
    }

    return ret;
}

CefRefPtr<CefResponseFilter> QCefClient::GetResourceResponseFilter(CefRefPtr<CefBrowser> browser,
                                                                   CefRefPtr<CefFrame> frame,
                                                                   CefRefPtr<CefRequest> request,
                                                                   CefRefPtr<CefResponse> response)
{
    QCEF_DEBUG();

    CefRefPtr<CefResponseFilter> ret;

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        ret = delegate->GetResourceResponseFilter(browser, frame, request, response);
    }

    return ret;
}

void QCefClient::OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
                                        CefRefPtr<CefFrame> frame,
                                        CefRefPtr<CefRequest> request,
                                        CefRefPtr<CefResponse> response,
                                        URLRequestStatus status,
                                        int64 received_content_length)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnResourceLoadComplete(browser, frame, request, response, status, received_content_length);
    }
}

void QCefClient::OnProtocolExecution(CefRefPtr<CefBrowser> browser,
                                     CefRefPtr<CefFrame> frame,
                                     CefRefPtr<CefRequest> request,
                                     bool& allow_os_execution)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnProtocolExecution(browser, frame, request, allow_os_execution);
    }
}



//////////////////////////////////////////////////////////////////////////
//CefDownloadHandler
void QCefClient::OnBeforeDownload(CefRefPtr<CefBrowser> browser,
                                         CefRefPtr<CefDownloadItem> download_item,
                                         const CefString& suggested_name,
                                         CefRefPtr<CefBeforeDownloadCallback> callback)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnBeforeDownload(browser, download_item, suggested_name, callback);
    }
}

void QCefClient::OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
                                          CefRefPtr<CefDownloadItem> download_item,
                                          CefRefPtr<CefDownloadItemCallback> callback)
{
    QCEF_DEBUG();

    QCefDelegate * delegate = m_delegate.loadAcquire();
    if (delegate != nullptr)
    {
        delegate->OnDownloadUpdated(browser, download_item, callback);
    }
}

